// MIT License
// 开源地址：https://gitee.com/co1024/AbcMvc
// Copyright (c) 2021-2023 1024
// Abc.Mvc=Furion+EF+SqlSugar+Pear layui admin.

using Furion.DynamicApiController;

namespace Abc.Application.HtAdminServices;

/// <summary>
///     菜单表
/// </summary>
[ApiDescriptionSettings("HtAdmin", Name = "HtMenu")]
[MaApi("API", "HtMenu", "菜单管理", PCode = "API")]
[IgnoreAntiforgeryToken]
public class HtMenuService : IHtMenuService, ITransient, IDynamicApiController
{
    private readonly ILogger<HtMenuService> _logger;
    private readonly IRepository<SysMenu> _repository;

    public HtMenuService(ILogger<HtMenuService> logger
        , IRepository<SysMenu> repository)
    {
        _logger = logger;
        _repository = repository;
    }

    /// <summary>
    ///     新增或更新一条
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [MaPermission("新增或更新一条", "InsertOrUpdate")]
    public async Task InsertOrUpdate(HtMenuInput input)
    {
        if (input.Id > 0)
        {
            var dbentity = await _repository.FirstOrDefaultAsync(r => r.Id == input.Id);
            input.Adapt(dbentity);
            dbentity.IsAutoGeneration = false; //修改后，设置为不是自动生成，防止下次生成覆盖
            dbentity.Icon = $"layui-icon {dbentity.Icon}";
        }
        else
        {
            var add = input.Adapt<SysMenu>();
            add.Icon = $"layui-icon {add.Icon}";
            var newEntity = await _repository.InsertAsync(add);
        }
    }

    /// <summary>
    ///     删除一条
    /// </summary>
    /// <param name="id"></param>
    [MaPermission("删除一条", "Delete")]
    public async Task Delete(long id)
    {
        var dbmenu = await _repository.FirstAsync(o => o.Id == id);
        if (dbmenu.IsSystem == false)
            await _repository.Where(o => o.Id == id).ExecuteDeleteAsync();
        else
            Oops.Bah("系统菜单不能删除");
    }

    /// <summary>
    ///     批量假删除
    /// </summary>
    /// <param name="ids">需要删除的数据，多条以英文逗号隔开</param>
    [MaPermission("批量假删除", "BatchFakeDelete")]
    public async Task BatchFakeDelete(string ids)
    {
        var idtemps = ids.ToIntList();
        await _repository.Where(r => idtemps.Any(a => a == r.Id))
            .ExecuteUpdateAsync(u =>
                u.SetProperty(f => f.IsDeleted, n => true)
            );
    }

    /// <summary>
    ///     查询一条[跟踪实体]
    /// </summary>
    /// <param name="id"></param>
    [MaPermission("查询一条", "Get")]
    public async Task<HtMenuOut> Get(long id)
    {
        var dbentity = await _repository.DetachedEntities.FirstOrDefaultAsync(o => o.Id == id);
        if (dbentity == null) return null;
        return dbentity.Adapt<HtMenuOut>();
    }

    /// <summary>
    ///     查询一条[跟踪实体]
    /// </summary>
    /// <param name="code"></param>
    [MaPermission("查询一条", "GetByCode")]
    public async Task<HtMenuOut> GetByCode(string code)
    {
        var entity = await _repository.DetachedEntities.FirstOrDefaultAsync(o => o.Code == code);
        return entity?.Adapt<HtMenuOut>();
    }

    /// <summary>
    ///     分页查询
    /// </summary>
    /// <param name="searchQuery"></param>
    /// <returns></returns>
    [MaPermission("分页查询", "GetAllByPage")]
    public async Task<LayuiPagedList<HtMenuOut>> GetAllByPageToLayui(HtMenuQuery searchQuery)
    {
        var queryable = _repository.DetachedEntities.AsQueryable();

        if (!string.IsNullOrWhiteSpace(searchQuery.AreaName))
        {
            var kw = searchQuery.AreaName.ToLower();
            queryable = queryable.Where(o => o.Area != null && o.Area.ToLower() == kw);
        }

        if (!string.IsNullOrWhiteSpace(searchQuery.KeyWords))
        {
            var kw = searchQuery.KeyWords.ToLower();
            queryable = queryable.Where(o => o.Name.Contains(kw)
                                             || (o.Code != null && o.Code.ToLower().Contains(kw))
                                             || (o.Url != null && o.Url.ToLower().Contains(kw)));
        }

        var resultpage = queryable.OrderByDescending(o => o.Id).ProjectToType<HtMenuOut>();
        //foreach (var item in resultpage.data)
        //{
        //    // item.PermissionStr = entities.First(o => o.Id == item.Id).Permissions?.Select(o => o.Name)?.StringJoin(",") ?? "";
        //}

        var pagedlist = await resultpage.ToLayuiPagedListAsync(searchQuery.Page, searchQuery.Limit);
        pagedlist.data = GetMenus(pagedlist.data);

        return pagedlist;
    }

    /// <summary>
    ///     设置状态
    /// </summary>
    /// <param name="id"></param>
    /// <param name="state"></param>
    /// <param name="field">字段名</param>
    /// <returns></returns>
    [MaPermission("设置状态", "SetState")]
    public async Task SetState(long id, bool state, string field)
    {
        var entity = await _repository.FirstAsync(o => o.Id == id);
        switch (field.ToLower())
        {
            case "isenable": entity.IsEnable = state; break;
            case "isexpand": entity.IsExpand = state; break;
            case "isdisuse": entity.IsDisuse = state; break;
            case "issystem": entity.IsSystem = state; break;
            case "isshow": entity.IsShow = state; break;
            case "isautogeneration": entity.IsAutoGeneration = state; break;
            case "isdeleted": entity.IsDeleted = state; break;
        }
    }

    /// <summary>
    ///     获取MenuPermission Area 集合
    /// </summary>
    /// <returns></returns>
    [MaPermission("获取MenuPermission Area 集合", "GetMenuAreas")]
    public async Task<List<string>> GetMenuAreas()
    {
        var areas = await _repository.DetachedEntities.Select(o => o.Area).Distinct().ToListAsync();
        return areas;
    }

    /// <summary>
    ///     查询菜单下拉树
    /// </summary>
    /// <returns></returns>
    [MaPermission("查询菜单下拉树", "GetDtree")]
    public async Task<Dtree> GetDtree(string pid = "")
    {
        var dtreeEntities = await _repository.DetachedEntities
            .Select(o => new DtreeEntity { id = o.Code, pid = o.PCode, name = o.Name, sort = o.Sort })
            .ToListAsync();
        var dtree = dtreeEntities.GetDtree(pid);
        return dtree;
    }

    /// <summary>
    ///     获取后台左侧菜单列表
    /// </summary>
    /// <param name="area">区域</param>
    /// <returns></returns>
    [MaPermission("获取后台左侧菜单列表", "GetMenus")]
    public async Task<List<PearMenuItemOut>> GetMenus(string area)
    {
        var dbmenus = await _repository.DetachedEntities
            .Where(o => o.IsEnable && o.IsShow)
            .Select(o => new PearMenuItem
            {
                MenuType = o.MenuType,
                Code = o.Code,
                PCode = o.PCode,
                Name = o.Name,
                Icon = o.Icon,
                Sort = o.Sort,
                Url = o.Url
            }).ToListAsync();
        var rmenus = dbmenus.GetMenus(area);
        return rmenus;
    }

    private List<HtMenuOut> GetMenus(IEnumerable<HtMenuOut> menus, string pCode = "")
    {
        var menuItems = new List<HtMenuOut>();
        foreach (var menuitem in menus.Where(o => o.PCode != null && o.PCode.ToLower() == pCode.ToLower())
                     .OrderBy(o => o.Sort))
        {
            if (!string.IsNullOrWhiteSpace(menuitem.Code) &&
                menus.Any(o => o.PCode != null && o.PCode.ToLower() == pCode.ToLower()))
                menuitem.children = GetMenus(menus, menuitem.Code);
            menuitem.IsParent = !string.IsNullOrWhiteSpace(pCode);
            menuItems.Add(menuitem);
        }

        return menuItems;
    }
}